/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.java; import java.io.*; import java.util.*; import javax.swing.text.Position; import javax.swing.text.StyledDocument; import org.openide.src.*; import org.openide.text.*; /** An implementation of ElementPrinter which chaches the tokens * between marks. * * @author Petr Hamernik */ class CodeGenerator { /** Generates the javadoc for the given element. * @param element The element which is used for printing * @param impl The implementation where is the printed text inserted */ public static void regenerateJavaDoc(final Element element, final ElementImpl impl) throws SourceException { try { final PositionRef docBegin; if (impl.docBounds != null) { docBegin = impl.docBounds.getBegin(); } else { docBegin = null; } final StyledDocument doc = impl.bounds.getBegin().getEditorSupport().openDocument(); Util.ExceptionRunnable run = new Util.ExceptionRunnable() { public void run() throws Exception { PositionRef begin; PositionBounds bounds; if (docBegin != null) { begin = docBegin; bounds = impl.docBounds; } else { bounds = SourceElementImpl.createNewLineBoundsAt(impl.getJavaDocPosition()); begin = bounds.getBegin(); } StringWriter stringWriter = new StringWriter(); Writer indentWriter = Util.findIndentWriter(doc, begin.getOffset(), stringWriter); ElementPrinterImpl printer = new ElementPrinterImpl(indentWriter, element, ElementPrinter.JAVADOC_BEGIN, ElementPrinter.JAVADOC_END); try { element.print(printer); } catch (ElementPrinterInterruptException e) { } bounds.setText(stringWriter.toString()); if (impl.docBounds == null) { impl.docBounds = bounds; } } }; Util.runAtomic(doc, run); } catch (Exception e) { throw new SourceException(e.getMessage()); } } /** Generates the header for the given element. * @param element The element which is used for printing * @param impl The implementation where is the printed text inserted */ public static void regenerateHeader(final Element element, final ElementImpl impl) throws SourceException { if (impl.headerBounds != null) { try { final PositionRef headerBegin = impl.headerBounds.getBegin(); final StyledDocument doc = headerBegin.getEditorSupport().openDocument(); Util.ExceptionRunnable run = new Util.ExceptionRunnable() { public void run() throws Exception { StringWriter stringWriter = new StringWriter(); Writer indentWriter = Util.findIndentWriter(doc, headerBegin.getOffset(), stringWriter); ElementPrinterImpl printer = new ElementPrinterImpl(indentWriter, element, ElementPrinter.HEADER_BEGIN, ElementPrinter.HEADER_END); try { element.print(printer); } catch (ElementPrinterInterruptException e) { } impl.headerBounds.setText(stringWriter.toString()); } }; Util.runAtomic(doc, run); } catch (Exception e) { throw new SourceException(e.getMessage()); } } } /** Generates the header for the given element. * @param element The element which is used for printing * @param impl The implementation where is the printed text inserted */ public static void regenerateElement(final Element element, final ElementImpl impl) throws SourceException { if (impl.bounds != null) { try { final PositionRef begin = impl.bounds.getBegin(); final EditorSupport editor = begin.getEditorSupport(); final StyledDocument doc = editor.openDocument(); Util.ExceptionRunnable run = new Util.ExceptionRunnable() { public void run() throws Exception { StringWriter stringWriter = new StringWriter(); Writer indentWriter = Util.findIndentWriter(doc, begin.getOffset(), stringWriter); WholeElementPrinter printer = new WholeElementPrinter(indentWriter, stringWriter, element, impl, editor); try { element.print(printer); } catch (ElementPrinterInterruptException e) { } impl.bounds.setText(stringWriter.toString()); printer.finish(); } }; Util.runAtomic(doc, run); } catch (Exception e) { if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N e.printStackTrace(); SourceException exc = (e instanceof SourceException) ? (SourceException) e : new SourceException(e.getMessage()); throw exc; } } } static class WholeElementPrinter extends ElementPrinterImpl { StringWriter stringWriter; Element element; ElementImpl elementImpl; EditorSupport editor; HashMap marksMap; MarkData current; WholeElementPrinter(Writer writer, StringWriter stringWriter, Element element, ElementImpl elementImpl, EditorSupport editor) { super(writer); this.stringWriter = stringWriter; this.element = element; this.elementImpl = elementImpl; this.editor = editor; marksMap = initElementsMap(element, elementImpl); current = (MarkData) marksMap.get(element); } public void markNotify(Element el, int what) { if (current.element != el) { current = (MarkData) marksMap.get(el); } current.positions[what] = stringWriter.getBuffer().length(); } private HashMap initElementsMap(Element element, ElementImpl elementImpl) { if (element instanceof ClassElement) { HashMap map = new HashMap(25); // [ph] for creating this map we suppose that structure under element and elementImpl // is exactly the same (including order of subelements). This is reasonable assumption // because impl hierarchy is created in ElementsCollection class from element hierarchy. fillMapForClass(map, (ClassElement) element, (ClassElementImpl) elementImpl); return map; } else { HashMap map = new HashMap(2); map.put(element, new MarkData(element, elementImpl)); return map; } } private void fillMapForClass(HashMap map, ClassElement clazz, ClassElementImpl clazzImpl) { map.put(clazz, new MarkData(clazz, clazzImpl)); for (int i = 0; i < 5; i++) { Object[] elements = null; switch (i) { case 0: elements = clazz.getInitializers(); break; case 1: elements = clazz.getFields(); break; case 2: elements = clazz.getConstructors(); break; case 3: elements = clazz.getMethods(); break; case 4: elements = clazz.getClasses(); break; } if ((elements == null) || (elements.length == 0)) continue; Object[] elementImpls = null; switch (i) { case 0: elementImpls = clazzImpl.initializers.toArray(); break; case 1: elementImpls = clazzImpl.fields.toArray(); break; case 2: elementImpls = clazzImpl.constructors.toArray(); break; case 3: elementImpls = clazzImpl.methods.toArray(); break; case 4: elementImpls = clazzImpl.classes.toArray(); break; } if (i != 4) { for (int j = 0; j < elements.length; j++) { MarkData mark = new MarkData((Element) elements[j], (ElementImpl) ((Element)elementImpls[j]).getCookie(ElementImpl.class)); map.put(elements[j], mark); } } else { for (int j = 0; j < elements.length; j++) fillMapForClass(map, (ClassElement) elements[j], (ClassElementImpl) ((Element)elementImpls[j]).getCookie(ClassElementImpl.class)); } } } void finish() { int offset = elementImpl.bounds.getBegin().getOffset(); Iterator it = marksMap.values().iterator(); while (it.hasNext()) { MarkData data = (MarkData) it.next(); if (element != data.element) { data.elementImpl.bounds = createBounds(data.positions[ELEMENT_BEGIN] + offset, data.positions[ELEMENT_END] + offset); } data.elementImpl.docBounds = createBounds(data.positions[JAVADOC_BEGIN] + offset, data.positions[JAVADOC_END] + offset); data.elementImpl.headerBounds = createBounds(data.positions[HEADER_BEGIN] + offset, data.positions[HEADER_END] + offset); data.elementImpl.bodyBounds = createBounds(data.positions[BODY_BEGIN] + offset, data.positions[BODY_END] + offset); } } private PositionBounds createBounds(int begin, int end) { if ((begin == -1) || (end == -1)) return null; PositionRef posBegin = editor.createPositionRef(begin, Position.Bias.Forward); PositionRef posEnd = editor.createPositionRef(end, Position.Bias.Backward); return new PositionBounds(posBegin, posEnd); } } static class MarkData { Element element; ElementImpl elementImpl; int[] positions; MarkData(Element element, ElementImpl elementImpl) { this.element = element; this.elementImpl = elementImpl; positions = new int[8]; for (int i = 0; i < 8; i++) positions[i] = -1; } } // ================= methods ============================== static class ElementPrinterImpl implements ElementPrinter { PrintWriter writer; Element printedElement; int beginMark; int endMark; int status; ElementPrinterImpl(Writer writer) { this(writer, null, 0, 0); status = 1; } ElementPrinterImpl(Writer writer, Element printedElement, int beginMark, int endMark) { this.writer = new PrintWriter(writer); this.printedElement = printedElement; this.beginMark = beginMark; this.endMark = endMark; status = 0; } public boolean isBegin(Element element, int what) { return (printedElement == null) || ((element == printedElement) && (what == beginMark)); } public boolean isEnd(Element element, int what) { return (printedElement == element) && (what == endMark); } public void markNotify(Element element, int what) { } public String getString() { return writer.toString(); } /** Prints the given text. * @param text The text to write */ public void print(String text) throws ElementPrinterInterruptException { switch (status) { case 0: return; case 1: writer.print(text); break; case 2: throw new ElementPrinterInterruptException(); } } /** Prints the line. New-line character '\n' should be added. * @param text The line to write */ public void println(String text) throws ElementPrinterInterruptException { print(text); print("\n"); // NOI18N } /** Add the mark to the list, if the printer is currently caching * (status == 1) or this mark is the begin. * @param element The element to mark * @param what The kind of event */ private void mark(Element element, int what) throws ElementPrinterInterruptException { switch (status) { case 0: if (isBegin(element, what)) { markNotify(element, what); status = 1; } break; case 1: writer.flush(); markNotify(element, what); if (isEnd(element, what)) { status = 2; writer.close(); throw new ElementPrinterInterruptException(); } break; case 2: throw new ElementPrinterInterruptException(); } } /** Marks the notable point of the class element. * @param element The element. * @param what The kind of the event. It must be one of the integer * constants from this interface */ public void markClass(ClassElement element, int what) throws ElementPrinterInterruptException { mark(element, what); } /** Marks the notable point of the initializer element. * @param element The element. * @param what The kind of the event. It must be one of the integer * constants from this interface * @return always <CODE>true</CODE> */ public void markInitializer(InitializerElement element, int what) throws ElementPrinterInterruptException { mark(element, what); } /** Marks the notable point of the field element. * @param element The element. * @param what The kind of the event. It must be one of the integer * constants from this interface */ public void markField(FieldElement element, int what) throws ElementPrinterInterruptException { mark(element, what); } /** Marks the notable point of the constructor element. * @param element The element. * @param what The kind of the event. It must be one of the integer * constants from this interface */ public void markConstructor(ConstructorElement element, int what) throws ElementPrinterInterruptException { mark(element, what); } /** Marks the notable point of the method element. * @param element The element. * @param what The kind of the event. It must be one of the integer * constants from this interface */ public void markMethod(MethodElement element, int what) throws ElementPrinterInterruptException { mark(element, what); } } } /* * Log * 11 Gandalf-post-FCS1.9.1.0 2/24/00 Svatopluk Dedic JavaDoc re-creation * doesn't format method code * 10 Gandalf 1.9 1/12/00 Petr Hamernik i18n: perl script used ( * //NOI18N comments added ) * 9 Gandalf 1.8 1/10/00 Petr Hamernik regeneration of * ClassElements improved (AKA #4536) * 8 Gandalf 1.7 1/6/00 Petr Hamernik debug msgs removed * 7 Gandalf 1.6 1/6/00 Petr Hamernik fixed 4321 * 6 Gandalf 1.5 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 5 Gandalf 1.4 7/16/99 Petr Hamernik debug printline removed * 4 Gandalf 1.3 7/8/99 Petr Hamernik changes reflecting * org.openide.src changes * 3 Gandalf 1.2 6/9/99 Ian Formanek ---- Package Change To * org.openide ---- * 2 Gandalf 1.1 6/2/99 Petr Hamernik connections of java * sources * 1 Gandalf 1.0 5/10/99 Petr Hamernik * $ */